/**
 * \file erreurs.c
 * \author H4201
 */

/* MODULES USED */
#include <signal.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include "erreurs.h"
#include "../interface/messqueue.h"
#include "../interface/partage_simu.h"
#include "../interface/mutexpartage.h"

/*GLOBAL VARIABLES*/

/**
 * Descripteur de /BalErreurs
 */
static mqd_t bal_erreurs;

/**
 * Tableau permettant de connaitre l'état des sémaphores.
 * 1 = sémaphore libre
 * 0 = sémphore pris
 * */
static int etat_semaphores[5];

/*EXPORTED FUNCTIONS*/

/**
 * Fonction qui sert de point d'entré au thread "Erreurs"
 * \param parameter inutilisé ici
 */
void* erreurs (void *parameter) {
    (void)parameter;
    int i;
    for (i=0; i<5; i++) {
	etat_semaphores[i] = 1;
    }
    
    struct sigaction au_usr2;
	au_usr2.sa_handler = arret_urgence;
	au_usr2.sa_flags = 0;
    message_t message;
    
    bal_erreurs = mq_open(BAL_ERREURS_NAME, O_RDWR);
    mqd_t bal_messages = mq_open(BAL_MESSAGES_NAME, O_WRONLY);

    
	// Démasquage du signal SIGUSR2
	sigemptyset(&au_usr2.sa_mask);
	sigaddset(&au_usr2.sa_mask, SIGUSR2);
	sigprocmask(SIG_UNBLOCK, &au_usr2.sa_mask, NULL);
	// Association du signal au handler
	sigaction(SIGUSR2, &au_usr2, NULL);
    
    
    for (;;) {
	    // lecture de la file d'attente bal_erreurs
        mq_receive(bal_erreurs, (char *) &message, sizeof(message_t), NULL);
        fermer_clapet();
        mq_send(bal_messages, (char *) &message, sizeof(message_t), 1);
	
	switch (message.type) {
	    case ERRPIECE :
		etat_semaphores[0] = 0;
		break;
	    case ERRCARTON :
		etat_semaphores[1] = 0;
		break;
	    case ERRIMPR :
		etat_semaphores[2] = 0;
		break;
	    case ERRPALETTE :
		etat_semaphores[3] = 0;
		break;
	    case ERREMBAL :
		etat_semaphores[4] = 0;
		break;
	    default :
		break;	
	}
	    
	
	
        if (message.type == ARRET) {
            break;
        }
    }

    pthread_exit(NULL);
}

/**
 * Fonction associée au handler d'arret d'urgence
 * \param signum Inutilisé ici
 */
void arret_urgence(int signum) {
    // signum n'est pas utilisé ici
    (void) signum;
    printf("Arrêt d'urgence\n");
    message_t message_au;
    fermer_clapet();
    message_au.type = AU;
    mq_send(bal_erreurs, (char *) &message_au, sizeof(message_t), 31);
}

/**
 * Ferme le clapet
 */
void fermer_clapet() {
    g_shm->clapet = false;
}

/**
 * Ouvre le clapet
 */
void ouvrir_clapet() {
    g_shm->clapet = true;
}

/**
 * Fait un dépot sur les sémaphores étant bloqués
 */
void remplir_semaphore() {
    if (etat_semaphores[0] == 0) {
	sem_post(&sem_err_timeout);
	etat_semaphores[0] = 1;
    }
    
    if (etat_semaphores[1] == 0) {
	sem_post(&sem_carton_absent);
	etat_semaphores[1] = 1;
    }
    
    if (etat_semaphores[2] == 0) {
	sem_post(&sem_err_imprim);
	etat_semaphores[2] = 1;
    }
    
    
    if (etat_semaphores[3] == 0) {
	sem_post(&sem_palette_absente);
	etat_semaphores[3] = 1;
    }
    
    if (etat_semaphores[4] == 0) {
	sem_post(&sem_err_embal);
	etat_semaphores[4] = 1;
    }
}

/**
 * Indique si un sémaphore est bloqué.
 * \return 1 si tous les sémphore sont débloqués, 0 sinon
 */
int statut_semaphore() {
    int i;
    for (i=0; i<5; i++) {
	if (etat_semaphores[i] == 0) {
	    return 0;
	}
    }
    return 1;
}
